//
//
// import 'dart:async';
// import 'dart:io';
// import 'dart:ui' as ui;
//
// import 'package:flutter/foundation.dart';
// import 'package:flutter/material.dart';
// import 'package:xim/http/ase.dart';
//
// /// 密码图片处理器
// class EncryptNetWorkImageProvider extends ImageProvider<NetworkImage> implements NetworkImage{
//
//   final String plaintextAESKey;
//
//   const EncryptNetWorkImageProvider(this.url, this.plaintextAESKey, { this.scale = 1.0, this.headers });
//
//   @override
//   final String url;
//
//   @override
//   final double scale;
//
//   @override
//   final Map<String, String>? headers;
//
//   @override
//   Future<NetworkImage> obtainKey(ImageConfiguration configuration) {
//     return SynchronousFuture<NetworkImage>(this);
//   }
//
//   // @override
//   // ImageStreamCompleter load(NetworkImage key, DecoderCallback decode) {
//   //   // Ownership of this controller is handed off to [_loadAsync]; it is that
//   //   // method's responsibility to close the controller's stream when the image
//   //   // has been loaded or an error is thrown.
//   //   final StreamController<ImageChunkEvent> chunkEvents = StreamController<ImageChunkEvent>();
//   //
//   //   return MultiFrameImageStreamCompleter(
//   //     codec: _loadAsync(key as NetworkImage, chunkEvents, decodeDeprecated: decode),
//   //     chunkEvents: chunkEvents.stream,
//   //     scale: key.scale,
//   //     debugLabel: key.url,
//   //     informationCollector: () => <DiagnosticsNode>[
//   //       DiagnosticsProperty<ImageProvider>('Image provider', this),
//   //       DiagnosticsProperty<NetworkImage>('Image key', key),
//   //     ],
//   //   );
//   // }
//
//   @override
//   ImageStreamCompleter loadBuffer(NetworkImage key, DecoderBufferCallback decode) {
//     // Ownership of this controller is handed off to [_loadAsync]; it is that
//     // method's responsibility to close the controller's stream when the image
//     // has been loaded or an error is thrown.
//     final StreamController<ImageChunkEvent> chunkEvents = StreamController<ImageChunkEvent>();
//
//     return MultiFrameImageStreamCompleter(
//       codec: _loadAsync(key as NetworkImage, chunkEvents, decodeBufferDeprecated: decode),
//       chunkEvents: chunkEvents.stream,
//       scale: key.scale,
//       debugLabel: key.url,
//       informationCollector: () => <DiagnosticsNode>[
//         DiagnosticsProperty<ImageProvider>('Image provider', this),
//         DiagnosticsProperty<NetworkImage>('Image key', key),
//       ],
//     );
//   }
//
//   @override
//   ImageStreamCompleter loadImage(NetworkImage key, ImageDecoderCallback decode) {
//     // Ownership of this controller is handed off to [_loadAsync]; it is that
//     // method's responsibility to close the controller's stream when the image
//     // has been loaded or an error is thrown.
//     final StreamController<ImageChunkEvent> chunkEvents = StreamController<ImageChunkEvent>();
//     return MultiFrameImageStreamCompleter(
//       chunkEvents: chunkEvents.stream,
//       codec: _loadAsync(key as NetworkImage, decode, chunkEvents),
//       scale: key.scale,
//       debugLabel: key.url,
//       informationCollector: _imageStreamInformationCollector(key),
//     );
//
//     // return MultiFrameImageStreamCompleter(
//     //   codec: _loadAsync(key as NetworkImage, chunkEvents, decode: decode),
//     //   chunkEvents: chunkEvents.stream,
//     //   scale: key.scale,
//     //   debugLabel: key.url,
//     //   informationCollector: () => <DiagnosticsNode>[
//     //     DiagnosticsProperty<ImageProvider>('Image provider', this),
//     //     DiagnosticsProperty<NetworkImage>('Image key', key),
//     //   ],
//     // );
//     //
//   }
//
//   // Do not access this field directly; use [_httpClient] instead.
//   // We set `autoUncompress` to false to ensure that we can trust the value of
//   // the `Content-Length` HTTP header. We automatically uncompress the content
//   // in our call to [consolidateHttpClientResponseBytes].
//   static final HttpClient _sharedHttpClient = HttpClient()..autoUncompress = false;
//
//   static HttpClient get _httpClient {
//     HttpClient? client;
//     assert(() {
//       if (debugNetworkImageHttpClientProvider != null) {
//         client = debugNetworkImageHttpClientProvider!();
//       }
//       return true;
//     }());
//     return client ?? _sharedHttpClient;
//   }
//
//   // Future<ui.Codec> _loadAsync(
//   //     NetworkImage key,
//   //     StreamController<ImageChunkEvent> chunkEvents, {
//   //       ImageDecoderCallback? decode,
//   //       DecoderBufferCallback? decodeBufferDeprecated,
//   //       // DecoderCallback? decodeDeprecated,
//   //     }) async {
//   //   try {
//   //     assert(key == this);
//   //
//   //     final Uri resolved = Uri.base.resolve(key.url);
//   //
//   //     final HttpClientRequest request = await _httpClient.getUrl(resolved);
//   //
//   //     headers?.forEach((String name, String value) {
//   //       request.headers.add(name, value);
//   //     });
//   //     final HttpClientResponse response = await request.close();
//   //     if (response.statusCode != HttpStatus.ok) {
//   //       // The network may be only temporarily unavailable, or the file will be
//   //       // added on the server later. Avoid having future calls to resolve
//   //       // fail to check the network again.
//   //       await response.drain<List<int>>(<int>[]);
//   //       throw NetworkImageLoadException(statusCode: response.statusCode, uri: resolved);
//   //     }
//   //
//   //     Uint8List bytes = await consolidateHttpClientResponseBytes(
//   //       response,
//   //       onBytesReceived: (int cumulative, int? total) {
//   //         chunkEvents.add(ImageChunkEvent(
//   //           cumulativeBytesLoaded: cumulative,
//   //           expectedTotalBytes: total,
//   //         ));
//   //       },
//   //     );
//   //     // aes 解密
//   //     if (bytes.lengthInBytes == 0) {
//   //       throw Exception('NetworkImage is an empty file: $resolved');
//   //     }
//   //     bytes = AES.decryptAesBytes(aesKey: plaintextAESKey, encryptData: bytes);
//   //     if (decode != null) {
//   //       final ui.ImmutableBuffer buffer = await ui.ImmutableBuffer.fromUint8List(bytes);
//   //       return decode(buffer);
//   //     } else if (decodeBufferDeprecated != null) {
//   //       final ui.ImmutableBuffer buffer = await ui.ImmutableBuffer.fromUint8List(bytes);
//   //       return decodeBufferDeprecated(buffer);
//   //     } else {
//   //       // assert(decodeDeprecated != null);
//   //       // return decodeDeprecated!(bytes);
//   //     }
//   //   } catch (e) {
//   //     // Depending on where the exception was thrown, the image cache may not
//   //     // have had a chance to track the key in the cache at all.
//   //     // Schedule a microtask to give the cache a chance to add the key.
//   //     scheduleMicrotask(() {
//   //       PaintingBinding.instance.imageCache.evict(key);
//   //     });
//   //     rethrow;
//   //   } finally {
//   //     chunkEvents.close();
//   //   }
//   // }
//
//   @override
//   bool operator ==(Object other) {
//     if (other.runtimeType != runtimeType) {
//       return false;
//     }
//     return other is NetworkImage
//         && other.url == url
//         && other.scale == scale;
//   }
//
//   @override
//   int get hashCode => Object.hash(url, scale);
//
//   @override
//   String toString() => '${objectRuntimeType(this, 'NetworkImage')}("$url", scale: $scale)';
//
// }